package com.mspbots.rule.exceptions.attendance;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.mspbots.cw.request.AttendanceDTO;
import com.mspbots.cw.request.TenantUserConfigurationDTO;
import lombok.extern.slf4j.Slf4j;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName com.mspbots.rule.exceptions.attendance.BeforeWorkEnd
 * @Description TODO
 * @Author Jun
 * @Date 2019/9/17 17:45
 * @Version 1.0
 **/
@Slf4j
@Rule(name = "BeforeWorkEnd",
        description = "Dear [User], you are scheduled to finish the day at [Time], please check the pending tasks, " +
                "if you are ready to end the day, please Type: \"Out\" or \"EOD\", " +
                "mspbots will do a end of day check for you and check you out for the day if there is nothing pending. ")
public class BeforeWorkEnd extends AttendanceBaseRule {

    private LocalDateTime workDateTime;
    private String endTimeStr = "";

    @Condition
    public boolean condition(@Fact(FACT) TenantUserConfigurationDTO tenantUserConfigurationDTO) {
        try {

            if (!setUserMapping(tenantUserConfigurationDTO.getTenantUserId())
                    || super.checkDayMessage(tenantUserConfigurationDTO.getTenantUserId())) {
                return false;
            }
            LocalTime endTime = getTodayEndTime(userWorkTimeConfig);

            if (endTime == null) {
                log.info("tenant user [{}] endTime is null [{}]",
                        tenantUserConfigurationDTO.getTenantUserId(), LocalDateTime.now());
                return false;
            }

            workDateTime = LocalDateTime.of(LocalDateTime.now().plusHours(tz).toLocalDate(), endTime);
            LocalDateTime workDateTimeUTC = workDateTime.minusHours(tz);

            Integer mins = this.tenantRuleDTO.getRuleParams().get("Mins").asInt();

            if (LocalDateTime.now().isBefore(workDateTimeUTC.minusMinutes(mins))
                    || LocalDateTime.now().isAfter(workDateTimeUTC)) {
                return false;
            }

            // check if user has BOD
            AttendanceDTO attendanceDTO = getAttendance(Map.of("tenantId", tenantUserConfigurationDTO.getTenantId(),
                    "userId", tenantUserConfigurationDTO.getTenantUserId(), "type", "OUT"));
            if (ObjectUtils.isEmpty(attendanceDTO) || !in12Hour(attendanceDTO)) {
                return true;
            }

            return false;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("BeforeWorkEnd error : [{}] ", tenantUserConfigurationDTO.getTenantUserId());
        }
        return false;
    }

    @Action
    public void action(@Fact(FACT) TenantUserConfigurationDTO tenantUserConfigurationDTO) {
        String now = LocalDateTime.now().plusHours(tz).format(DateTimeFormatter.ofPattern("MM/dd HH:mm"));
        Map<String, Object> params = new HashMap<>(16);
        params.put("USER", tenantUserMappingDTO.getFirstName());
        params.put("EndTime", styleParam(endTimeStr));
        params.put("TimeZone", styleParam(tzStr));
        String message = StrUtil.format(this.tenantRuleDTO.getTemplate(), params);

        String suffixMessage = new StringBuilder()
                .append("--")
                .append("<span style='color:#999d9c;font-size:10px;'>")
                .append(suffixUserName())
                .append("[")
                .append(now)
                .append(" ").append(tzStr)
                .append("]")
                .append("</span>").toString();

        messages.setMessage(message + "<br>" + suffixEscalation() + suffixMessage);
        messages.setBusinessType("attendance");

        if (messages.getMessage().indexOf("{EndTime}") < 0) {
            insertMessage(messages);
        } else {
            log.error("BeforeWorkEnd error: {}", endTimeStr, tenantUserConfigurationDTO.getTenantUserId(), tenantUserConfigurationDTO.getKeywordValue());
        }
    }

    private LocalTime getTodayEndTime(JSONObject jsonObject) {
        try {
            DayOfWeek dayOfWeek = LocalDateTime.now().plusHours(tz).getDayOfWeek();
            JSONArray workTimeArr = jsonObject.get("workTimes", JSONArray.class);
            JSONObject workTime = (JSONObject) workTimeArr.get(dayOfWeek.getValue() - 1);
            String startTimeStr = workTime.getStr("endTime");
            endTimeStr = startTimeStr;// like 17:00
            return StringUtils.isEmpty(startTimeStr) ? null : LocalTime.parse(startTimeStr + ":00");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("BeforeWorkEnd getTodayEndTime : {}", e.getMessage());
        }
        return null;
    }
}
